package com.anrong.sdk.util.log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Application;
import android.os.Environment;
import android.util.Log;
import android.util.SparseArray;

/**
 * 
 * @ClassName: LogUtil
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author dongtianhao
 * @date 2016年7月11日 下午3:02:05
 *
 */
public final class LogUtil {

	private static boolean logoff = true;
	private static boolean isPrint = true;
	private static int level = Log.WARN; //
	private static String STORAGE_PATH = Environment
			.getExternalStorageDirectory().getPath();
	private static String saveDirName = "/anrong/log/";
	private static String saveDir;

	public static String getSaveDir() {
		return saveDir;
	}

	// if (BuildConfig.DEBUG && Log.isLoggable("TAG", Log.VERBOSE)) {
	// Log.v("TAG", message);
	// }

	/**
	 * 
	 * @Title: init
	 * @Description: logUtil初始化
	 * @param level
	 *            指定把高于或等于Error的信息保存到sdcard文件，因为最高的error权限是6，也就是说这里指定为大于6，
	 *            即使是错误信息也不会写入sdcard里面
	 * @param saveDirName
	 *            目录名字，任意指定,如果不指定就在/anrong/log/目录下
	 * @param logoff
	 *            屏蔽打印
	 * @return void 返回类型
	 * @throws
	 */
	public static void init(int level, String saveDirName, boolean logoff) {
		LogUtil.level = level;
		LogUtil.saveDirName = saveDirName;
		LogUtil.logoff = logoff;
	}

	public static void init(int level, String saveDirName, boolean logoff,
			boolean isPrint) {
		LogUtil.level = level;
		LogUtil.saveDirName = saveDirName;
		LogUtil.logoff = logoff;
		LogUtil.isPrint = isPrint;
	}

	/**
	 * 
	 * @Title: trace
	 * @Description: (这里用一句话描述这个方法的作用)
	 * @param type
	 * @param tag
	 * @param msg
	 *            设定文件
	 * @return void 返回类型
	 * @throws
	 */
	public static void trace(final int type, String tag, final String msg) {
		if (logoff && type == Log.DEBUG) {
			Log.d(tag, msg);
		}
		switch (type) {
		case Log.VERBOSE:
			Log.v(tag, msg);
			break;
		case Log.INFO:
			Log.i(tag, msg);
			break;
		case Log.WARN:
			Log.w(tag, msg);
			break;
		case Log.ERROR:
			Log.e(tag, msg);
			break;
		}
		// Write to file
		if (isPrint && type >= level) {
			new Thread() {
				public void run() {
					writeLog(type, msg, true);
				}
			}.start();
		}
	}

	/**
	 * Custom Log output style
	 * 
	 * @param type
	 *            Log type log的类型（error，warn等等）
	 * @param tag
	 *            TAG tag:输出标志
	 * @param msg
	 *            输出日志 Log message
	 * @param isContinueWrite
	 *            isContinueWrite:默认是true，即是上面没有这个参数的方法，
	 *            表示继续在原有文件写入，如果是false则创建一个新的覆盖原来的它。
	 */
	public static void trace(final int type, final String tag,
			final String msg, final boolean isContinueWrite) {
		if (logoff && type == Log.DEBUG) {
			Log.d(tag, msg);
		}
		switch (type) {
		case Log.VERBOSE:
			Log.v(tag, msg);
			break;
		case Log.DEBUG:
			Log.d(tag, msg);
			break;
		case Log.INFO:
			Log.i(tag, msg);
			break;
		case Log.WARN:
			Log.w(tag, msg);
			break;
		case Log.ERROR:
			Log.e(tag, msg);
			break;
		}
		// Write to file
		if (isPrint && type >= level) {
			new Thread() {
				public void run() {
					writeLog(type, msg, isContinueWrite);
				}
			}.start();
		}
	}

	/**
	 * Write log file to the SDcard
	 * 
	 * @param type
	 * @param msg
	 */
	private static void writeLog(int type, String msg, boolean isContinueWrite) {
		if (!Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED)) {
			return;
		}
		try {
			SparseArray<String> logMap = new SparseArray<String>();
			logMap.put(Log.VERBOSE, " VERBOSE ");
			logMap.put(Log.DEBUG, " DEBUG ");
			logMap.put(Log.INFO, " INFO ");
			logMap.put(Log.WARN, " WARN ");
			logMap.put(Log.ERROR, " ERROR ");

			final StackTraceElement tag = new Throwable().fillInStackTrace()
					.getStackTrace()[2];

			msg = new StringBuilder().append("\r\n")
					.append(getDateformat(Dateformater.SS.getValue()))
					.append(logMap.get(type)).append(tag.getClassName())
					.append(" - ").append(tag.getMethodName()).append("(): ")
					.append(msg).toString();

			final String fileName = new StringBuffer().append("log-")
					.append(getDateformat(Dateformater.DD.getValue()))
					.append(".log").toString();

			saveDir = STORAGE_PATH + saveDirName;
			recordLog(saveDir, fileName, msg, isContinueWrite);
		} catch (Exception e) {
			LogUtil.trace(Log.ERROR, "LogUtil: ", e.getMessage());
		}
	}

	/**
	 * Write log
	 * 
	 * @param logDir
	 *            Log path to save
	 * @param fileName
	 * @param msg
	 *            Log content
	 * @param bool
	 *            Save as type, false override save, true before file add save
	 */
	private static void recordLog(String logDir, String fileName, String msg,
			boolean bool) {
		try {
			createDir(logDir);
			final File saveFile = new File(new StringBuffer().append(logDir)
					.append("/").append(fileName).toString());
			if (!bool && saveFile.exists()) {
				saveFile.delete();
				saveFile.createNewFile();
				final FileOutputStream fos = new FileOutputStream(saveFile,
						bool);
				fos.write(msg.getBytes());
				fos.close();
			} else if (bool && saveFile.exists()) {
				final FileOutputStream fos = new FileOutputStream(saveFile,
						bool);
				fos.write(msg.getBytes());
				fos.close();
			} else if (bool && !saveFile.exists()) {
				saveFile.createNewFile();
				final FileOutputStream fos = new FileOutputStream(saveFile,
						bool);
				fos.write(msg.getBytes());
				fos.close();
			} else if (!bool && !saveFile.exists()) {
				saveFile.createNewFile();
				final FileOutputStream fos = new FileOutputStream(saveFile,
						bool);
				fos.write(msg.getBytes());
				fos.close();
			}
		} catch (IOException e) {
			recordLog(logDir, fileName, msg, bool);
		}
	}

	public static GlobalExceptionHandler processGlobalException(
			Application application, boolean isWriteIntoFile) {
		if (application != null) {
			GlobalExceptionHandler handler = new GlobalExceptionHandler(
					application, isWriteIntoFile);
			Thread.setDefaultUncaughtExceptionHandler(handler);
			return handler;
		}
		return null;
	}

	private static String getDateformat(String pattern) {
		final DateFormat format = new SimpleDateFormat(pattern);
		return format.format(new Date());
	}

	private static File createDir(String dir) {
		final File file = new File(dir);
		if (!file.exists()) {
			file.mkdirs();
		}
		return file;
	}

}
